/**
 * 
 */
package com.dingding.order.core.orderlist.dao.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.dao.impl.BaseDaoImpl;
import com.dingding.common.core.beans.CarShareOrder;
import com.dingding.common.core.beans.Userroute;
import com.dingding.common.core.config.ServiceCode;
import com.dingding.common.core.util.DateFormatUtil;
import com.dingding.common.core.util.GetDistanceUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.order.core.orderlist.dao.IGetNearbyOrderListDao;
import com.dingding.order.dto.orderlist.ComparatorUtil;
import com.dingding.order.dto.orderlist.NearbyOrderList;
import com.dingding.order.dto.orderlist.NearbyOrderListSQL;
import com.dingding.order.dto.orderlist.ReqGetNearbyOrderListDTO;
import com.dingding.order.dto.orderlist.ResCoupon;

/**
 * @ClassName: GetDriverNearbyOrderListDaoImpl
 * @Description:司机获取附近乘客列表
 * @author zhouxuan
 * @date 2016年6月4日 下午8:06:15
 */
@Component("getNearbyOrderListDao")
public class GetNearbyOrderListDaoImpl extends BaseDaoImpl<CarShareOrder> implements IGetNearbyOrderListDao {
	/**
	 * @Title: getNearbyOrderList
	 * @Description:获取附近用户订单列表
	 * @param reqGetNearbyOrderListDTO
	 * @author zhouxuan
	 * @return List<NearbyOrderList>
	 */
	@Override
	@Transactional(readOnly = true)
	public List<NearbyOrderList> getNearbyOrderList(ReqGetNearbyOrderListDTO reqGetNearbyOrderListDTO,
			ResCoupon resCoupon) {
		// 创建用于存储获取附近列表的对象
		List<Object[]> objects = null;

		// 用户类型(1：车主 2：乘客)
		Integer userType = reqGetNearbyOrderListDTO.getUserType();

		// 判断用户类型
		if (userType == 1) {// 1：车主 2：乘客
			try {
				objects = super.sqlQueryListObj(
						NearbyOrderListSQL.DriverGetNearByUserList(reqGetNearbyOrderListDTO.getSortCondition()), false,
						reqGetNearbyOrderListDTO.getUserId(),
						(reqGetNearbyOrderListDTO.getPageIndex() - 1) * reqGetNearbyOrderListDTO.getPageSize(),
						reqGetNearbyOrderListDTO.getPageSize());
			} catch (Exception e) {
				log.error("司机获取附近用户订单列表时出现异常   类：" + this.getClass() + " getNearbyOrderList()", e);
			}
		} else {
			try {
				objects = super.sqlQueryListObj(
						NearbyOrderListSQL.PassengerGetNearByUserList(reqGetNearbyOrderListDTO.getSortCondition()),
						false, reqGetNearbyOrderListDTO.getUserId(),
						(reqGetNearbyOrderListDTO.getPageIndex() - 1) * reqGetNearbyOrderListDTO.getPageSize(),
						reqGetNearbyOrderListDTO.getPageSize());
			} catch (Exception e) {
				log.error("乘客获取附近用户订单列表时出现异常   类：" + this.getClass() + " getNearbyOrderList()", e);
			}
		}
		// 根据用户Id获取开启的路线列表
		List<Userroute> userRoutes = this.getUserRoute(reqGetNearbyOrderListDTO.getUserId());

		// 创建用于存储附近列表的变量
		List<NearbyOrderList> list = null;

		// 过滤附近订单列表
		if (objects != null && objects.size() > 0) {
			list = this.getNearbyOrderLists(objects, reqGetNearbyOrderListDTO, userRoutes, resCoupon);
		}
		return list;
	}

	/**
	 * @Title: getUserRoute
	 * @Description: 根据用户Id获取用户开启的路线列表
	 * @param userId
	 *            用户Id
	 * @author yuHaiQing
	 * @return List<Userroute> 返回类型
	 */
	@Transactional(readOnly = true)
	public List<Userroute> getUserRoute(String userId) {

		// 根据用户Id获取其启用的路线列表
		List<Object[]> routeObjects = super.sqlQueryListObj(NearbyOrderListSQL.GET_ALL_ENABLE_USERROUTE, false, userId);

		// 创建用于存储用户路线列表的对象
		List<Userroute> userRoutes = new ArrayList<Userroute>();

		// 数据转换(将List<Object[]>类型转为List<Userroute>)
		this.getUserRoutes(routeObjects, userRoutes);

		return userRoutes;
	}

	/**
	 * @Title: getUserRoutes
	 * @Description: 数据转换(将List<Object[]>类型转为List<Userroute>)
	 * @param objects
	 *            路线列表数据
	 * @param userroutes
	 *            存储路线列表对象
	 * @author yuHaiQing
	 * @return void 返回类型
	 */
	public void getUserRoutes(List<Object[]> objects, List<Userroute> userroutes) {

		for (Object[] obj : objects) {

			Userroute userroute = new Userroute();

			// 路线Id
			if (obj[0] != null) {
				userroute.setUrId(obj[0].toString());
			}
			// 出发时间
			if (obj[1] != null) {
				userroute.setSetOutTime((Date) obj[1]);
			}
			// 起点经度
			if (obj[2] != null) {
				userroute.setStartLongitude(ToolUtil.castDouble(obj[2]));
			}
			// 起点纬度
			if (obj[3] != null) {
				userroute.setStartLatitude(ToolUtil.castDouble(obj[3]));
			}
			// 终点经度
			if (obj[4] != null) {
				userroute.setPurposeLongitude(ToolUtil.castDouble(obj[4]));
			}
			// 终点纬度
			if (obj[5] != null) {
				userroute.setPurposeLatitude(ToolUtil.castDouble(obj[5]));
			}
			// 路线类型
			if (obj[6] != null) {
				userroute.setRouteType(ToolUtil.castInteger(obj[6]));
			}
			userroutes.add(userroute);
		}
	}

	/**
	 * @Title: getNearbyUserLists
	 * @Description: 将List<Object[]>转为List <ResGetNearbyUserList>
	 * @param objects
	 *            List<Object[]>类型的附近用户列表
	 * @return List<ResGetNearbyUserList> 返回类型
	 */
	public List<NearbyOrderList> getNearbyOrderLists(List<Object[]> objects,
			ReqGetNearbyOrderListDTO reqGetNearbyOrderListDTO, List<Userroute> userRoutes, ResCoupon resCoupon) {

		// 创建用于响应客户端的集合对象(获取附近用户列表集合)
		List<NearbyOrderList> list = new ArrayList<NearbyOrderList>();

		// 获取当前用户订单
		for (Object[] obj : objects) {

			// 判断要使用的字段是否为空
			boolean flag = getOrderInfoListValidate(obj, reqGetNearbyOrderListDTO);

			if (!flag) {
				log.info("当前订单不符合条件");
				continue;
			}

			// 创建用于存储附近订单的对象
			NearbyOrderList resGetNearbyUserList = new NearbyOrderList();

			// 筛选条件（1：上班 2：下班 3：附近 4：长途）
			Integer screenCondition = reqGetNearbyOrderListDTO.getScreenCondition();

			// 用户当前位置距离订单起点距离
			BigDecimal currentDistance = this.getCurrentDistance(obj, reqGetNearbyOrderListDTO.getCurrentLongitude(),
					reqGetNearbyOrderListDTO.getCurrentLatitude());

			// 筛选条件（1：上班 2：下班 3：附近 4：长途）
			if (screenCondition.equals(1)) { // 上班

				// 如果获取到的路线信息为空，则退出本次循环
				if (userRoutes == null || userRoutes.size() <= 0) {
					break;
				}

				this.commuteRouteMethod(obj, resGetNearbyUserList, userRoutes, 1,
						reqGetNearbyOrderListDTO.getUserType(), resCoupon);

			} else if (screenCondition.equals(2)) { // 下班

				// 如果获取到的路线信息为空，则退出本次循环
				if (userRoutes == null || userRoutes.size() <= 0) {
					break;
				}

				this.commuteRouteMethod(obj, resGetNearbyUserList, userRoutes, 2,
						reqGetNearbyOrderListDTO.getUserType(), resCoupon);

			} else if (screenCondition.equals(3)) { // 附近

				// 判断用户距离订单起点距离是否在规定范围内
				if (currentDistance.compareTo(ServiceCode.NEARBY_RANGE) > 0) {
					continue;
				}

				// 数据转换
				this.nearbyMethod(resGetNearbyUserList, obj, reqGetNearbyOrderListDTO.getUserType(), resCoupon);

			} else if (screenCondition.equals(4)) { // 长途
				// 数据转换
				this.longDistanceMethod(obj, resGetNearbyUserList, reqGetNearbyOrderListDTO.getPayCity(),
						reqGetNearbyOrderListDTO.getUserType(), resCoupon);
			}

			if (resGetNearbyUserList != null && resGetNearbyUserList.getOrderStatus() != null) {

				// 给订单添加一个用户距离订单起点距离
				resGetNearbyUserList.setStartDistance(currentDistance);

				list.add(resGetNearbyUserList);
			}

		}

		if (list != null && list.size() > 0 && (reqGetNearbyOrderListDTO.getSortCondition() == 3
				|| reqGetNearbyOrderListDTO.getSortCondition() == 1)) {
			Collections.sort(list, new ComparatorUtil());
		}
		return list;
	}

	public NearbyOrderList longDistanceMethod(Object[] obj, NearbyOrderList resGetNearbyUserList, String city,
			Integer userType, ResCoupon resCoupon) {

		/**
		 * obj[23] 订单里程 obj[24] 下单城市
		 */
		// 订单里程
		double orderDistance = ToolUtil.castDouble(obj[23]);
		// 下单城市
		String payCity = obj[24].toString();

		// 判断出发地是否同城，订单里程是否属于长途拼车范围
		if (!payCity.equals(city) || orderDistance <= 50.0) {
			log.info("不符合长途拼车的筛选条件");
			return null;
		}

		// 数据转换
		this.getResGetNearByUserList(resGetNearbyUserList, obj, userType, resCoupon);

		return resGetNearbyUserList;
	}

	/**
	 * @Title: nearbyMethod
	 * @Description: 获取订单列表-附近
	 * @param resGetNearbyUserList
	 *            响应Bean
	 * @param obj
	 *            订单数据
	 * @author yuHaiQing
	 * @return ResGetNearbyUserList 返回类型
	 */
	public NearbyOrderList nearbyMethod(NearbyOrderList resGetNearbyUserList, Object[] obj, Integer userType,
			ResCoupon resCoupon) {

		// 数据转换
		this.getResGetNearByUserList(resGetNearbyUserList, obj, userType, resCoupon);

		return resGetNearbyUserList;
	}

	/**
	 * @Title: getOrderListValidate
	 * @Description: 获取订单列表验证
	 * @param obj
	 *            订单数据
	 * @param reqGetNearbyUserList
	 *            客户端请求参数
	 * @param userRoutes
	 *            用户路线列表
	 * @author yuHaiQing
	 * @return boolean 返回类型 @throws
	 */
	public boolean getOrderInfoListValidate(Object[] obj, ReqGetNearbyOrderListDTO reqGetNearbyOrderList) {

		// 筛选条件（1：附近 2：顺路 3：长途）
		if (reqGetNearbyOrderList.getScreenCondition().equals(2)) {
			// 出发时间
			if (obj[4] == null) {
				return false;
			}
			// 起点纬度
			if (obj[6] == null) {
				return false;
			}
			// 起点经度
			if (obj[7] == null) {
				return false;
			}
			// 终点经度
			if (obj[9] == null) {
				return false;
			}
			// 终点纬度
			if (obj[10] == null) {
				return false;
			}

		} else if (reqGetNearbyOrderList.getScreenCondition().equals(3)) { // 长途
			// 订单里程
			if (obj[23] == null) {
				return false;
			}
			// 下单城市
			if (obj[24] == null) {
				return false;
			}
		}

		return true;
	}

	/**
	 * @Title: getCurrentDistance
	 * @Description: 获取当前用户距离订单起点距离
	 * @author yuHaiQing
	 * @return double 返回类型 @throws
	 */
	public BigDecimal getCurrentDistance(Object[] obj, double currentLongitude, double currentLatitude) {

		// 订单起点经度
		double startLongitude = ToolUtil.castDouble(obj[6]);
		// 订单起点纬度
		double startLatitude = ToolUtil.castDouble(obj[7]);

		// 计算用户当前位置距离订单起点位置的距离
		BigDecimal currentDistance = GetDistanceUtil.GetDistance(currentLongitude, currentLatitude, startLongitude,
				startLatitude);

		return currentDistance.setScale(1, BigDecimal.ROUND_UP);
	}

	/**
	 * @Title: regularRouteMethod
	 * @Description: 获取订单列表-顺路
	 * @param obj
	 *            订单数据
	 * @param resGetNearbyUserList
	 *            响应Bean
	 * @param userRoutes
	 *            路线列表
	 * @param routeType
	 *            路线类型
	 * @param userType
	 *            当前用户角色
	 * @author yuHaiQing
	 * @return void 返回类型
	 */
	public NearbyOrderList commuteRouteMethod(Object[] obj, NearbyOrderList resGetNearbyUserList,
			List<Userroute> userRoutes, Integer routeType, Integer userType, ResCoupon resCoupon) {

		// 订单出发时间
		Date currentTime = (Date) obj[4];
		// 订单起点经度
		double startLng = ToolUtil.castDouble(obj[6]);
		// 订单起点纬度
		double startLat = ToolUtil.castDouble(obj[7]);
		// 订单终点经度
		double endLng = ToolUtil.castDouble(obj[9]);
		// 订单终点纬度
		double endLat = ToolUtil.castDouble(obj[10]);

		// 遍历全部路线列表
		for (Userroute userRoute : userRoutes) {

			if (userRoute == null || userRoute.getStartLongitude() == null || userRoute.getStartLatitude() == null
					|| userRoute.getPurposeLongitude() == null || userRoute.getPurposeLatitude() == null
					|| userRoute.getRouteType() != routeType) {
				log.info("路线中起点或终点的经纬度为空或无该类型路线");
				continue;
			}

			// 用户路线起点距离订单起点距离
			BigDecimal startRange = GetDistanceUtil.GetDistance(startLng, startLat, userRoute.getStartLongitude(),
					userRoute.getStartLatitude());
			// 用户路线终点距离订单终点距离
			BigDecimal endRange = GetDistanceUtil.GetDistance(endLng, endLat, userRoute.getPurposeLongitude(),
					userRoute.getPurposeLatitude());

			// 判断两者的出发时间是否小于30分钟
			long minute = 0;
			try {
				minute = DateFormatUtil.getTimeIntervalS(userRoute.getSetOutTime(), currentTime);
			} catch (Exception e) {
				log.error("获取附近订单-顺路，获取两个时间点的间隔时时出现异常  类：" + this.getClass() + " regularRouteMethod()");
				e.printStackTrace();
			}

			if (startRange.compareTo(new BigDecimal(4)) > 0 || endRange.compareTo(new BigDecimal(4)) > 0 || minute > 30) {
				log.info("顺路匹配订单时，起点距离、终点距离或者出发时间不在规定范围内");
				continue;
			}

			// 数据转换
			this.getResGetNearByUserList(resGetNearbyUserList, obj, userType, resCoupon);

			break;
		}
		return resGetNearbyUserList;
	}

	/**
	 * @Title: getResGetNearByUserList @Description: 数据转换 @param
	 *         getNearbyUserList 存储订单信息的对象 @param obj 订单信息 @author
	 *         yuHaiQing @return ResGetNearbyUserList 返回类型 @throws
	 */
	public NearbyOrderList getResGetNearByUserList(NearbyOrderList getNearbyOrderList, Object[] obj, Integer userType,
			ResCoupon resCoupon) {

		// 乘客Id
		if (obj[0] != null) {
			getNearbyOrderList.setOtherSideId(obj[0].toString());
		}
		// 订单Id
		if (obj[1] != null) {

			// 当前订单Id是父订单还是子订单
			if (userType == 1) { // 子订单
				getNearbyOrderList.setSubOrder(obj[1].toString());
			} else { // 父订单
				getNearbyOrderList.setParentOrder(obj[1].toString());
			}

		}
		// 昵称
		if (obj[2] != null) {
			getNearbyOrderList.setNickName(obj[2].toString());
		}
		// 用户头像
		if (obj[3] != null) {
			getNearbyOrderList.setUserAvatar(ToolUtil.imageAddress(obj[3].toString()));
		}
		String titleTime = null;
		// 出发时间
		if (obj[4] != null) {
			titleTime = DateFormatUtil.getMMddEHHss(obj[4]);
			getNearbyOrderList.setSetOutTime((Date) obj[4]);
		}
		// 起始地
		if (obj[5] != null) {
			getNearbyOrderList.setStartAddress(obj[5].toString());
		}
		// 起始地纬度
		if (obj[6] != null) {
			getNearbyOrderList.setStartLongitude(ToolUtil.castDouble(obj[6]));
		}
		// 起始地经度
		if (obj[7] != null) {
			getNearbyOrderList.setStartLatitude(ToolUtil.castDouble(obj[7]));
		}

		// 目的地
		if (obj[8] != null) {
			getNearbyOrderList.setEndAddress(obj[8].toString());
		}
		// 目的地经度
		if (obj[9] != null) {
			getNearbyOrderList.setEndLongitude(ToolUtil.castDouble(obj[9]));
		}
		// 目的地纬度
		if (obj[10] != null) {
			getNearbyOrderList.setEndLatitude(ToolUtil.castDouble(obj[10]));
		}
		// 总金额
		if (obj[11] != null) {

			if (userType == 1) {
				// 总金额
				getNearbyOrderList.setTotalMoney(new BigDecimal(obj[11].toString()));
				// 订单费用
				getNearbyOrderList.setOrderCost(new BigDecimal(obj[11].toString()));
			} else if (userType == 2) {

				BigDecimal totalMoney = new BigDecimal(obj[11].toString()).add(new BigDecimal(2));

				// 判断优惠金额是否为空
				if (resCoupon != null && resCoupon.getCouponMoney() != null) {
					// 实际支付金额
					totalMoney = totalMoney.add(new BigDecimal(resCoupon.getCouponMoney()));

					if (totalMoney.compareTo(new BigDecimal(resCoupon.getCouponMoney())) < 0) {
						totalMoney = new BigDecimal(0);
					}
				}
				// 总金额
				getNearbyOrderList.setTotalMoney(totalMoney);

				// 订单费用
				getNearbyOrderList.setOrderCost(new BigDecimal(obj[11].toString()));
			}

			// 平台费用
			getNearbyOrderList.setPlatformCost(new BigDecimal(obj[11].toString()));
		}
		// 订单状态
		if (obj[12] != null) {
			getNearbyOrderList.setOrderStatus(1);
		}
		// 红包
		if (obj[13] != null) {
			getNearbyOrderList.setRedBag(ToolUtil.castInteger(obj[13]));
		}
		// 留言
		if (obj[14] != null) {
			getNearbyOrderList.setMessage(obj[14].toString());
		}
		// 人数
		if (obj[15] != null) {
			getNearbyOrderList.setNumber(ToolUtil.castInteger(obj[15]));
		}
		// 手机号
		if (obj[16] != null) {
			getNearbyOrderList.setTelePhone(obj[16].toString());
			getNearbyOrderList.setTellPhone(obj[16].toString());
		}
		// 头像缩略图
		if (obj[17] != null) {
			getNearbyOrderList.setUserTabloidAvatar(ToolUtil.imageAddress(obj[17].toString()));
		}
		// 下单用户性别
		if (obj[18] != null) {
			getNearbyOrderList.setSex(ToolUtil.castInteger(obj[18]));
		}
		// 车牌号
		if (obj[19] != null) {
			getNearbyOrderList.setLisencePlate(obj[19].toString());
		}
		// 车辆型号
		if (obj[20] != null) {
			getNearbyOrderList.setVehicleModel(obj[20].toString());
		}
		// 车辆品牌
		if (obj[21] != null) {
			getNearbyOrderList.setVehicleType(obj[21].toString());
		}
		// 车辆颜色
		if (obj[22] != null) {
			getNearbyOrderList.setVehicleColor(obj[22].toString());
		}
		// 订单里程
		if (obj[23] != null) {
			getNearbyOrderList.setDistance(new BigDecimal(obj[23].toString()));
		}
		// 下单城市
		if (obj[24] != null) {
			getNearbyOrderList.setPayCity(obj[24].toString());
		}
		// 订单类型(1:普通 2:长途)
		if (obj[25] != null) {
			getNearbyOrderList.setIsLongDistance(ToolUtil.castInteger(obj[25]));
		}
		// 用户级别
		if (obj[26] != null) {
			getNearbyOrderList.setUserLevel(new BigDecimal(obj[26].toString()));
		}
		// 是否合乘
		if (obj[27] != null) {
			getNearbyOrderList.setIsCarShare(ToolUtil.castInteger(obj[27]));
		}
		// 出发条件
		if (obj[28] != null) {
			getNearbyOrderList.setSetOutCondition(ToolUtil.castInteger(obj[28]));
		}
		// 闲置座位数
		if (obj[29] != null) {
			getNearbyOrderList.setFreeSeat(ToolUtil.castInteger(obj[29]));
		}

		StringBuffer sBuffer = new StringBuffer();

		sBuffer.append(titleTime);

		getNearbyOrderList.setTitle(sBuffer.toString());

		return getNearbyOrderList;
	}

}
